
//获取变量类型
function varTypeof(data){
	let type=Object.prototype.toString.call(data);
	return type.replaceAll(/(\[object )|(\])/g,"").toLowerCase();
}
	
//echart扩展
function echartExtend(echartObj,channel,maxLen,worker){
	let obj=echartObj.getDom().querySelector('canvas');
	let step=0.1,left,right;
	if(worker)echartObj.worker=worker;
	echartObj.channel=channel;
	echartObj.maxLen=maxLen-1;
	echartObj.startPos=0;
	echartObj.endPos=echartObj.maxLen;
	//获取左右间隙
	reloadGap();
	//鼠标滚轮
	obj.onmousewheel=ev=>{
		ev.preventDefault();
		let bl=(ev.clientX-left)/(obj.offsetWidth-right-left);
		let changeLen=(echartObj.endPos-echartObj.startPos)*step;
		let leftNum=bl*changeLen;
		let rightNum=(1-bl)*changeLen;
		if(ev.deltaY>0){
			//缩小
			if(echartObj.startPos==0 && echartObj.endPos==echartObj.maxLen)return;
			echartObj.startPos-=leftNum;
			echartObj.endPos+=rightNum;
			if(echartObj.startPos<0)echartObj.startPos=0;
			if(echartObj.endPos>echartObj.maxLen)echartObj.endPos=echartObj.maxLen;
		}else{
			//放大
			if(echartObj.endPos-echartObj.startPos<50)return;
			echartObj.startPos+=leftNum;
			echartObj.endPos-=rightNum;
		}
		let start=echartObj.startPos/echartObj.maxLen;
		let end=echartObj.endPos/echartObj.maxLen;
		draw(start,end);
	}
	//鼠标拖动
	let posX=null;
	let w=obj.offsetWidth-right-left;
	let timer,startPos2,endPos2;
	obj.onmousemove=ev=>{
		if(timer)return;
		timer=setTimeout(()=>{
			timer=null;
			if(posX!=null){
				let c=ev.offsetX-posX;
				let len=Math.abs((c/w)*(echartObj.endPos-echartObj.startPos));
				if(c>0){//左移
					if(startPos2==0)return;
					if(echartObj.startPos-len<0)len=echartObj.startPos;
					startPos2=echartObj.startPos-len;
					endPos2=echartObj.endPos-len;
				}else{//右移
					if(endPos2==echartObj.maxLen)return;
					if(echartObj.endPos+len>echartObj.maxLen)len=echartObj.maxLen-echartObj.endPos;
					startPos2=echartObj.startPos+len;
					endPos2=echartObj.endPos+len;
				}
				let start=startPos2/echartObj.maxLen;
				let end=endPos2/echartObj.maxLen;
				draw(start,end);
			}
		},100);
	}
	obj.onmousedown=ev=>{
		posX=ev.offsetX;
		startPos2=echartObj.startPos;
		endPos2=echartObj.endPos;
	}
	obj.onmouseup=ev=>{
		posX=null;
		if(startPos2)echartObj.startPos=startPos2;
		if(endPos2)echartObj.endPos=endPos2;
	}
	obj.onmouseout=ev=>{
		posX=null;
		if(startPos2)echartObj.startPos=startPos2;
		if(endPos2)echartObj.endPos=endPos2;
	}
	
	//计算左右两边留白距离
	function reloadGap(){
		let grid=echartObj.getOption().grid[0];
		left=grid.left.indexOf('%')?obj.offsetWidth*grid.left.replace('%',"")/100:grid.left;
		right=grid.right.indexOf('%')?obj.offsetWidth*grid.right.replace('%',"")/100:grid.right;
	}
	
	//画图表 start end为开始位置和结束位置的百分比
	async function draw(start,end){
		let res=await echartObj.worker.extract({
			channel:echartObj.channel,
			start,
			end,
			resLen:2000
		});
		if(res.y.length==0)return;
		//有多组数据时
		let t=Date.now();
		if(res.isMultiData){
			let series=[];
			res.y.forEach(v=>series.push({data:v}));
			echartObj.setOption({
				series,
				xAxis:{data:res.x,interval:res.interval}
			});
		}else{
			echartObj.setOption({
				series:[{data:res.y}],
				xAxis:{data:res.x,interval:res.interval}
			});
		}
		let t2=Date.now()-t;
		if(t2>50)console.log('画图',t2);		
	}
	
	
	let timer2;
	echartObj.startUpdate=function(times=20){
		time2=true;
		function a(){
			if(!time2)return;
			setTimeout(()=>{
				if(channel && channel.newData){
					channel.newData=false;
					echartObj.reload();
				}
				a();
			},parseInt(1000/times));
		}
		a();
	}
	echartObj.stopUpdate=function(){
		timer2=false;
	}
	echartObj.reloadGap=reloadGap;
	echartObj.draw=draw;
	echartObj.setChannel=function(channel){
		echartObj.channel=channel;
	}
	echartObj.setMaxLen=function(len){
		echartObj.maxLen=len-1;
	}
	echartObj.reload=async function(){
		let start=echartObj.startPos/echartObj.maxLen;
		let end=echartObj.endPos/echartObj.maxLen;
		await draw(start,end);
	}
	return echartObj;
}	

//多个echart实例管理
function echartManager(){
	let objs=[];
	let timer3;
	let count=0;
	return {
		add(echartObj,channel,maxLen,worker){
			echartExtend(echartObj,channel,maxLen,worker);
			objs.push(echartObj);
		},
		del(echartObj){
			for(let i=0;i<objs.length;i++){
				if(objs[i]==echartObj){
					objs.splice(i,1);
					break;
				}
			}
		},
		startUpdate(times=20,debug=false){
			count=0;
			let t3=Date.now();
			function a(){
				if(!timer3)return;
				setTimeout(async ()=>{
					let t=Date.now();
					console.time();
					for(let i=0;i<objs.length;i++){
						await objs[i].reload();
					}
					console.timeEnd();
					if(debug){
						count++;
						if(count>100){
							timer3=false;
							console.log(`更新次数:${count},帧率:${(count/((Date.now()-t3)/1000)).toFixed(1)}`);
						}
					}
					a();
				},1000/times);
			}
			timer3=true;
			a();
		},
		stopUpdate(){
			timer3=false;
		}
	}
}

/**
 * worker回调处理
 */
function workerManager(){
	let worker=new Worker("./worker.js");
	let proxyhandle={},id=0;
	worker.onmessage=ev=>{
		let msg=ev.data;
		if(proxyhandle[msg.id]){
			proxyhandle[msg.id].resolve(msg.data);
			ev=null;
			delete proxyhandle[msg.id];
		}
	}
	return {		
		/**
			打开新连接
			opts.fs 采集频率
			opts.cacheTimeLen 缓存时长（秒）
			opts.channelNum 通道数
			opts.isMultiData 单通道是否多组数据
			opts.ws websocket地址
			opts.zip 服务器返回的是否需要zip解压
			opts.socketName  websockct标识名
		 */
		open(opts){
			if(!opts.socketName){
				console.error('websocket标识名称不存在，创建新连接失败');
				return;
			}
			id++;
			worker.postMessage({id,type:'open',...opts});
			return new Proxy({},{
				get(target,key){
					if(key=='then')return null;
					return (data={})=>{
						id=id>2000000?1:id+1;
						worker.postMessage({
							id,
							type:key,
							socketName:opts.socketName,
							...data
						});
						proxyhandle[id]=Promise.withResolvers();
						return proxyhandle[id].promise;
					}
				}
			});
		},
		destroy(){
			worker.terminate();
			worker=null;
			handleCallback={};
		},
		worker		
	}
}

export {
	echartManager,
	workerManager,
	echartExtend,
	varTypeof
}